/**
 ******************************************************************************
 * @file	driver_ls.c
 * @brief	TR700-STM32 光源驱动

- 2017-6-23,MenglongWu,MenglongWoo@aliyun.com
 *
 Copyright (C) 2017 桂林聚联科技有限公司, Inc. All Rights Reserved.
*/


#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include "stm32f10x_dma.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_spi.h"
#include "flash.h"
#include "stm32f10x.h"
#include "prj_type.h"
#include "usart.h"						//串口
#include "minishell-tiny.h"
#include "TR700Driver.h"
#include "project.h"



struct device_ls  dev_ls;

#define _541HZ (132)
#define _2KHZ (35)
#define _4KHZ (17)
// uint16_t  TIM_Period[3] = {_541HZ, _2KHZ, _4KHZ};			///<分频值133、36、18分别对应541Hz、2KHz、4KHz


// ***************************************************************************
// 连续激光器控制
void TIM3_Init(uint16_t  TIM_Period1310)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	/* TIM3 clock enable */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	/* ---------------------------------------------------------------
	TIM4 Configuration: Output Compare Timing Mode:
	TIM2CLK = 36 MHz, Prescaler = 7200, TIM2 counter clock = 7.2 MHz
	--------------------------------------------------------------- */
	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period	= TIM_Period1310;
	TIM_TimeBaseStructure.TIM_Prescaler	= (1000 - 1);
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode	= TIM_CounterMode_Up;

	// TIM_Cmd(TIM3, DISABLE);  	//初始化时候先关闭TIM3.。激光器输出CW波形
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	/* Clear TIM3 update pending flag[清除TIM3溢出中断标志] */
	TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
	/* TIM IT enable */
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	/* TIM3 enable counter */
	TIM_Cmd(TIM3, ENABLE);
	TIM_Cmd(TIM3, DISABLE);  	//初始化时候先关闭TIM3.。激光器输出CW波形

}


#define GROUP_CH1 	GPIOC
#define GROUP_CH2 	GPIOC
#define GROUP_CH3 	GPIOC

#define RCC_CH1 	RCC_APB2Periph_GPIOC
#define RCC_CH2 	RCC_APB2Periph_GPIOC
#define RCC_CH3 	RCC_APB2Periph_GPIOC

#define PIN_CH1 	GPIO_Pin_3
#define PIN_CH2 	GPIO_Pin_1
#define PIN_CH3 	GPIO_Pin_2
void Init_Laser()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_CH1, ENABLE);
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Pin	= PIN_CH1;
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_Out_PP;
	GPIO_Init(GROUP_CH1, &GPIO_InitStructure);
	// GPIO_SetBits(GROUP_CH1, PIN_CH1);
	GPIO_ResetBits(GROUP_CH1, PIN_CH1);

	RCC_APB2PeriphClockCmd(RCC_CH2, ENABLE);
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Pin	= PIN_CH2;
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_Out_PP;
	GPIO_Init(GROUP_CH2, &GPIO_InitStructure);
	// GPIO_SetBits(GROUP_CH2, PIN_CH2);
	GPIO_ResetBits(GROUP_CH2, PIN_CH2);

	RCC_APB2PeriphClockCmd(RCC_CH3, ENABLE);
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Pin	= PIN_CH3;
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_Out_PP;
	GPIO_Init(GROUP_CH3, &GPIO_InitStructure);
	// GPIO_SetBits(GROUP_CH3, PIN_CH3);
	GPIO_ResetBits(GROUP_CH3, PIN_CH3);







	TIM3_Init(_541HZ);
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	TIM_Cmd(TIM3, ENABLE);
}


// #define CTRL_CH_OFF  0
// #define CTRL_CH1     1
// #define CTRL_CH2     2
// #define CTRL_CH3     3
// void Ctrl_LaserChannel(int index)
void Ctrl_LaserChannel(struct device_ls *dev)
{
	int index = dev->ch;

	GPIO_TypeDef *group;
	uint16_t io;

	// printf("index %d\r\n", index);
	switch(index) {
	case CTRL_CH_OFF:
		// TODO 关闭定时器
		GPIO_ResetBits(GROUP_CH1, PIN_CH1);
		GPIO_ResetBits(GROUP_CH2, PIN_CH2);
		GPIO_ResetBits(GROUP_CH3, PIN_CH3);
		return;
	case CTRL_CH1:
		group = GROUP_CH1;
		io = PIN_CH1;
		break;
	case CTRL_CH2:
		group = GROUP_CH2;
		io = PIN_CH2;
		break;
	case CTRL_CH3:
		group = GROUP_CH3;
		io = PIN_CH3;
		break;
	default:
		return ;
	}
	GPIO_ResetBits(GROUP_CH1, PIN_CH1);
	GPIO_ResetBits(GROUP_CH2, PIN_CH2);
	GPIO_ResetBits(GROUP_CH3, PIN_CH3);

	GPIO_SetBits(group, io);
}


#define RCC_LASER_POWER 	RCC_APB2Periph_GPIOA
#define GROUP_LASER_POWER 	GPIOA
#define PIN_LASER_POWER 	GPIO_Pin_4

#define DAC_CH_LASER_POWER DAC_Channel_1
void Init_LaserPower(void)
{
	{
		GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(RCC_LASER_POWER, ENABLE);
		GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_2MHz;
		GPIO_InitStructure.GPIO_Pin	= PIN_LASER_POWER;
		GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_Out_PP;
		GPIO_Init(GROUP_LASER_POWER, &GPIO_InitStructure);
	}


	{
		DAC_InitTypeDef DAC_InitStructure ;
		/* GPIOA Periph clock enable */
		/* DAC Periph clock enable */
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

		DAC_InitStructure.DAC_Trigger        = DAC_Trigger_Software ;
		//设置为软件触发
		DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None ;
		DAC_InitStructure.DAC_OutputBuffer   = DAC_OutputBuffer_Enable ;

		/* DAC channel1 Configuration */
		DAC_Init(DAC_CH_LASER_POWER, &DAC_InitStructure);

		DAC_Cmd(DAC_CH_LASER_POWER, ENABLE);

		//实际对应神州IV开发板的DAC1引脚--PA.4 (PIN29)
	}
}

void Ctrl_LaserDAC(struct device_ls *v)
{
	short dac = (short)v->dac;

	if (dac > 4095) {
		dac = 4095;
	} else if (dac < 0) {
		dac = 0;
	}
	DAC_SoftwareTriggerCmd(DAC_Channel_1, DISABLE);
	DAC_SetChannel1Data(DAC_Align_12b_R, dac);
	DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);
}

void Ctrl_LaserPower(struct device_ls *v)
{
	Ctrl_LaserDAC(v);
}

// #define LASER_MODE_CW		0
// #define LASER_MODE_270Hz	1
// #define LASER_MODE_1KHZ		2
// #define LASER_MODE_2KHZ		3
// void Ctrl_LaserMode(int mode)
void Ctrl_LaserMode(struct device_ls *dev)
{
	int mode = dev->mode;
	int Period1 = _541HZ;

	switch (mode) {
	case LASER_MODE_CW:
		TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
		TIM_Cmd(TIM3, DISABLE);
		return;
	case LASER_MODE_270Hz:
		Period1 = _541HZ;

		break;
	case LASER_MODE_1KHZ:
		Period1 = _2KHZ;
		break;
	case LASER_MODE_2KHZ:
		Period1 = _4KHZ;
		break;
	default:
		break;
	}

	TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
	TIM3_Init(Period1);

	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	TIM_Cmd(TIM3, ENABLE);

	// TIM3_Init(_2KHZ);
	// TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	// TIM_Cmd(TIM3, ENABLE);
}

static __inline unsigned int Get_LaserChannel(struct device_ls *dev)
{
	return dev->ch;
}
/**
 * @brief	从dbm计算激光器控制参数
 * @param	null
 * @retval	null
 * @remarks
 * @see
 */

int Laser_dBm2Ctrl(float dbm, struct device_ls *dev)
{
	unsigned int ch = Get_LaserChannel(&dev_ls);
	unsigned short adj_adc = 0;
	unsigned short adj_dac = 0;


	switch(ch) {
	case 1:
		if (sys_param.ch1_en) {
			adj_adc = sys_param.ch1_10_adc;
			adj_dac = sys_param.ch1_10_dac;
		}
		break;
	case 2:
		if (sys_param.ch1_en) {
			adj_adc = sys_param.ch1_10_adc;
			adj_dac = sys_param.ch1_10_dac;
		}
		break;
	case 3:
		if (sys_param.ch1_en) {
			adj_adc = sys_param.ch1_10_adc;
			adj_dac = sys_param.ch1_10_dac;
		}
		break;
	default:  // 其他无用通道以及OFF模式
		break;
	}

#if CONFIG_USE_U_MATH
	dev->adc = (uint16_t)((_pow(10, (float)dbm / 10)) * adj_adc * 10);
	dev->dac = (uint16_t)((_pow(10, (float)dbm / 10)) * adj_dac * 10);
#else
	dev->adc = (uint16_t)((pow(10, (float)dbm / 10)) * adj_adc * 10);
	dev->dac = (uint16_t)((pow(10, (float)dbm / 10)) * adj_dac * 10);
#endif
	return 0;
}















//***************************************************************
// 稳态控制

struct control_p {
	int in_deta;	// 输入探测偏差值
	int out_ctrl;	// 输出控制值
	int next_time;  // 控制间隔ms
};


struct control_p g_p[] = {
	{ 50, -100, 1},
	{ 30, -20, 2},
	{ 20, -10, 3},
	{ 2,  -4, 4},
};

int Control_P(
    struct control_p *rule,
    int rule_size,
    int in_target,
    int in_current)
{
	int i;
	int deta = in_current - in_target;

	for (i = 0; i < rule_size; i++) {
		if (deta > rule[i].in_deta) {
			return rule[i].out_ctrl;
		} else if (-deta > rule[i].in_deta) {
			return -rule[i].out_ctrl;
		}
	}
	return 0;
}

struct in {
	int in_target;
	int in_current;
};

void AutoCtrl_LS()
{
	// 读取ADC
	unsigned short adc;
	int out;
	short  dac;

	adc = GetAD(AD_CH_LS);
	// 与目标值比较
	out = Control_P(
	          g_p,
	          sizeof(g_p) / sizeof(struct control_p),
	          dev_ls.adc, adc);
	dac = dev_ls.dac;
	dac = dac + out;
	// printf("t %d adc %d free %d  dac %d  \n",
	//        900, adc,
	//        out,
	//        dev_ls.dac);
	// 执行控制

	if (dac > 4095) {
		dac = 4095;
	} else if (dac < 0) {
		dac = 0;
	}
	dev_ls.dac = dac;

	Ctrl_LaserDAC(&dev_ls);
}
